#pragma once

#include <functional>
#include <unordered_map>
#include <list>
#include "Event.hpp"
#include "Alice/Math/Hash.hpp"
#include "Alice/Timer/Timer.h"
#include "Alice/Log/Log.h"

namespace Alice
{

/*
    预置的窗口事件
*/
const EventId WINDOW_QUIT = "WINDOW_QUIT"_hash;
const EventId WINDOW_RESIZED = "WINDOW_RESIZED"_hash;
const EventId WINDOW_INPUT = "WINDOW_INPUT"_hash;
const EventId WINDOW_MOUSE_LEFT = "WINDOW_MOUSE_LEFT"_hash;

/*
    实体事件宏，用来对同一实体区分不同事件
*/
// 碰撞事件
#define COLLISION(...) (__VA_ARGS__ + 23) << 1

/* 
    事件管理器
*/ 
class EventMngr
{
public:
    /* 
        添加一个事件监听
    */ 
    void AddListener(Event event, std::function<void(Event&)> const& func)
    {
        m_listeners[ event.GetId() ].push_back(func);
    }

    /* 
        发送一个事件 ID 并触发回调

        若回调函数使用到了外部的变量
        需要在创建 Event 对象后调用 SetParam 方法添加外部变量的值或指针
    */ 
    void SendEvent(Event event)
    {
        for (auto const& listener : m_listeners[ event.GetId() ])
        {
            listener(event);
        }
    }

    /*
        添加一个定时事件
    */
    void AddTimer(double interval_time, Event event, std::function<void()> const& func)
    {
        m_timer_listeners.insert({event.GetId(), func});
        m_event_interval_times.insert({event.GetId(), interval_time});
        m_event_previous_times.insert({event.GetId(), 0});
    }

    /*
        使用给定的计时器检查所有定时事件
        若满足条件则触发回调
    */
    void CheckTimerEvent(Timer& timer)
    {
        for (auto iter : m_timer_listeners)
        {
            double previous_time = m_event_previous_times[ iter.first ];
            double interval_time = m_event_interval_times[ iter.first ];
            double current_time = timer.CurrentTime();
            if (((current_time - previous_time) > interval_time))
            {
                iter.second();
                // 更新定时事件的计时器
                m_event_previous_times[ iter.first ] = current_time;
            }
        }
    }

private:
    // 事件对应的监听器集合
    // 当一个事件发生时，可能回调多个函数
    std::unordered_map<EventId, std::list<std::function<void(Event&)> > > m_listeners;
    // 定时事件集合
    std::unordered_map<EventId, std::function<void()> > m_timer_listeners;
    // 定时触发事件被触发的间隔时间
    std::unordered_map<EventId, double> m_event_interval_times;
    // 定时触发事件上一次被触发的时间
    std::unordered_map<EventId, double> m_event_previous_times;
};

} // namespace Alice
